package com.yycx.module.bus.provider.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.yycx.common.base.entity.EntityMap;
import com.yycx.common.base.utils.FlymeUtils;
import com.yycx.common.constants.CommonConstants;
import com.yycx.common.mybatis.base.service.impl.BaseServiceImpl;
import com.yycx.common.mybatis.model.ResultBody;
import com.yycx.common.mybatis.query.CriteriaDelete;
import com.yycx.common.mybatis.query.CriteriaQuery;
import com.yycx.common.mybatis.query.CriteriaSave;
import com.yycx.common.mybatis.query.CriteriaUpdate;
import com.yycx.common.security.OpenHelper;
import com.yycx.common.utils.ApiAssert;
import com.yycx.common.utils.DateUtils;
import com.yycx.module.bus.client.entity.*;
import com.yycx.module.bus.provider.mapper.BusSalemanBalanceMapper;
import com.yycx.module.bus.provider.service.BusDeptService;
import com.yycx.module.bus.provider.service.BusPaymentService;
import com.yycx.module.bus.provider.service.BusSalemanBalanceService;
import com.yycx.module.bus.provider.service.BusSalemanService;
import com.yycx.module.file.provider.service.SysFileService;
import com.yycx.module.system.client.entity.SysBank;
import com.yycx.module.system.provider.service.SysBankService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;

/**
 * 业务员资保金收支记录接口实现类
 *
 * @author flyme
 * @date 2023-08-24
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class BusSalemanBalanceServiceImpl extends BaseServiceImpl<BusSalemanBalanceMapper, BusSalemanBalance> implements BusSalemanBalanceService {


    @Resource
    private BusDeptService deptService;

    @Resource
    private BusSalemanService salemanService;

    @Resource
    private SysBankService bankService;

    @Resource
    private BusPaymentService paymentService;

    @Resource
    private SysFileService fileService;

    @Override
    public ResultBody beforeAdd(CriteriaSave cs, BusSalemanBalance bsb, EntityMap extra) {

        bsb.setOptType(CommonConstants.INT_1);
        bsb.setSaleManBalanceId(IdWorker.getId());
        bsb.setCompanyId(OpenHelper.getCompanyId());
        bsb.setAmountType(CommonConstants.INT_1);
        bsb.setBalanceState(CommonConstants.INT_0);
        bsb.setOriginalAmount(bsb.getAmount());
        bsb.setOrganizationId(OpenHelper.getOrganizationId());
        bsb.setVersion(1);
        bsb.setUserId(OpenHelper.getUserId());
        //添加保证金认款单
        BusPayment payment = paymentService.addSaleManBalancePayment(bsb);
        bsb.setRkId(payment.getPaymentId());
        return ResultBody.ok();
    }

    @Override
    public void afterGet(CriteriaQuery cq, EntityMap result) {
        Long deptId = result.getLong("deptId");
        BusDept dept = deptService.getById(deptId);
        if (FlymeUtils.isNotEmpty(dept)) {
            result.put("deptName", dept.getDeptName());
        }
        Long saleManId = result.getLong("saleManId");
        BusSaleman saleMan = salemanService.getById(saleManId);
        if (FlymeUtils.isNotEmpty(saleMan)) {
            result.put("saleManName", saleMan.getSaleManName());
        }
        Long bankId = result.getLong("bankId");
        SysBank bank = bankService.getById(bankId);
        if (FlymeUtils.isNotEmpty(bank)) {
            result.put("bankName", bank.getBankName());
        }
        super.afterGet(cq, result);
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public ResultBody beforePageList(CriteriaQuery<BusSalemanBalance> cq, BusSalemanBalance bsb, EntityMap requestMap) {
        cq.orderByDesc("bsb.createTime");
        return ResultBody.ok();
    }

    @Override
    public ResultBody beforeEdit(CriteriaUpdate<BusSalemanBalance> cu, BusSalemanBalance salemanBalance, EntityMap extra) {
        salemanBalance.setUserId(OpenHelper.getUserId());
        return super.beforeEdit(cu, salemanBalance, extra);
    }

    @Override
    public ResultBody afterEdit(CriteriaUpdate cu, BusSalemanBalance salemanBalance, EntityMap extra) {
        paymentService.addSaleManBalancePayment(salemanBalance);
        return super.afterEdit(cu, salemanBalance, extra);
    }

    @Override
    public ResultBody afterDelete(CriteriaDelete cd, Serializable[] ids) {
        Serializable id = cd.getIdValue();
        fileService.deleteByBusId(id.toString());
        return super.afterDelete(cd, ids);
    }


    /**
     * 根据订单ID查询
     *
     * @param orderId
     * @return
     */
    @Override
    public List<BusSalemanBalance> selectListByOrderId(Serializable orderId) {
        CriteriaQuery cq = new CriteriaQuery(BusCustomBalance.class);
        cq.eq(true, "orderId", orderId);
        return list(cq);
    }

    @Override
    public boolean removeByOrderId(Serializable orderId) {
        CriteriaDelete cu = new CriteriaDelete<>();
        cu.eq(true, "orderId", orderId);
        return remove(cu);
    }

    /**
     * 删除资保金抵扣并更新账户余额
     *
     * @param orderId
     */
    @Override
    public void updateSaleManBalance(Serializable orderId) {
        List<BusSalemanBalance> saleManBalance = selectListByOrderId(orderId);
        if (FlymeUtils.isNotEmpty(saleManBalance)) {
            for (BusSalemanBalance salemanBalance : saleManBalance) {
                Long saleManBalanceId = salemanBalance.getSaleManBalanceId();
                if (FlymeUtils.isNotEmpty(saleManBalanceId)) {
                    revokeOrderDetailsUse(saleManBalanceId);
                }
            }
        }
    }

    /**
     * 拆分金额
     *
     * @param saleManBalanceId
     * @param amount
     * @param orderId
     * @param orderDetailsId
     * @return
     */
    @Override
    public BusSalemanBalance cfAmount(Long saleManBalanceId, BigDecimal amount, String orderId, String orderDetailsId) {
        BusSalemanBalance saleManBalance = getById(saleManBalanceId);
        if (FlymeUtils.isNotEmpty(saleManBalance)) {
            BigDecimal oldAmount = saleManBalance.getAmount();
            BigDecimal surplusAmount = oldAmount.subtract(amount);
            ApiAssert.gezero("资保金余额不足", surplusAmount);
            if (FlymeUtils.gtzero(surplusAmount)) {
                saleManBalance.setAmount(surplusAmount);
                BusSalemanBalance newObj = new BusSalemanBalance();
                BeanUtil.copyProperties(saleManBalance, newObj);
                newObj.setAmount(amount);
                newObj.setParentId(saleManBalanceId);
                newObj.setOrderId(orderId);
                newObj.setOptType(2);
                newObj.setOrderDetailsId(orderDetailsId);
                newObj.setSaleManBalanceId(IdWorker.getId());
                save(newObj);
                updateById(saleManBalance);
                return newObj;
            } else {
                saleManBalance.setOrderId(orderId);
                saleManBalance.setOrderDetailsId(orderDetailsId);
                updateById(saleManBalance);
                return saleManBalance;
            }
        }
        return null;
    }

    /**
     * 抵扣资保金账户金额
     *
     * @param saleManBalanceId
     * @param amount
     * @param orderId
     * @param orderDetailsId
     * @return
     */
    @Override
    public BusSalemanBalance deductionAmount(Long saleManBalanceId, BigDecimal customBond, String orderId, String orderDetailsId) {
        BusSalemanBalance saleManBalance = getById(saleManBalanceId);
        if (FlymeUtils.isNotEmpty(saleManBalance)) {
            BigDecimal oldAmount = saleManBalance.getAmount();
            BigDecimal surplusAmount = oldAmount.subtract(customBond);
            ApiAssert.gezero("资保金余额不足", surplusAmount);
            if (FlymeUtils.gtzero(surplusAmount)) {
                return saleManBalance;
            }
        }
        return null;
    }

    /**
     * 撤销余额和订单的关联
     *
     * @param saleManBalanceId
     * @return
     */
    @Override
    public Boolean revokeOrderDetailsUse(Long saleManBalanceId) {
        BusSalemanBalance saleManBalance = getById(saleManBalanceId);
        if (FlymeUtils.isNotEmpty(saleManBalance)) {
            BigDecimal oldAmount = saleManBalance.getAmount();
            Long parentId = saleManBalance.getParentId();
            if (FlymeUtils.isNotEmpty(parentId)) {
                BusSalemanBalance parent = getById(parentId);
                BigDecimal parentAmount = parent.getAmount().add(oldAmount);
                parent.setAmount(parentAmount);
                removeById(saleManBalanceId);
                updateById(parent);
            } else {
                //父ID为空时仅需要清空关联ID
                saleManBalance.setOrderId(null);
                saleManBalance.setOrderDetailsId(null);
                updateById(saleManBalance);
            }

        }
        return true;
    }

    /**
     * 撤销拆分
     *
     * @param saleManBalanceId
     * @return
     */
    @Override
    public ResultBody revokeCfAmount(Long saleManBalanceId) {
        BusSalemanBalance saleManBalance = getById(saleManBalanceId);
        if (FlymeUtils.isNotEmpty(saleManBalance)) {
            BigDecimal oldAmount = saleManBalance.getAmount();
            Long parentId = saleManBalance.getParentId();
            if (FlymeUtils.isNotEmpty(parentId)) {
                BusSalemanBalance parent = getById(parentId);
                BigDecimal parentAmount = parent.getAmount().add(oldAmount);
                parent.setAmount(parentAmount);
                removeById(saleManBalanceId);
                updateById(parent);
            }
        }
        return ResultBody.ok("撤销成功");
    }

    @Override
    public BigDecimal totalAmount(Long saleManId, Long companyId) {
        CriteriaQuery<BusSalemanBalance> cq = new CriteriaQuery<>(BusSalemanBalance.class);
        cq.select("sum(amount)");
        cq.eq(true, "saleManId", saleManId);
        cq.eq(true, "companyId", companyId);
        BigDecimal amount = getObj(cq, e -> new BigDecimal(e.toString()));
        if (FlymeUtils.isEmpty(amount)) {
            amount = new BigDecimal("0");
        }
        return amount;
    }

    @Override
    public void updateCfAmount(Long saleManBalanceId, BigDecimal amount) {
        BusSalemanBalance saleManBalance = getById(saleManBalanceId);
        if (FlymeUtils.isNotEmpty(saleManBalance)) {
            BigDecimal oldAmount = saleManBalance.getAmount();
            BigDecimal diffAmount = oldAmount.subtract(amount);
            if (FlymeUtils.nezero(diffAmount)) {
                saleManBalance.setAmount(amount);
                updateById(saleManBalance);
                Long parentId = saleManBalance.getParentId();
                if (FlymeUtils.isNotEmpty(parentId)) {
                    BusSalemanBalance parent = getById(parentId);
                    BigDecimal parentAmount = parent.getAmount().add(diffAmount);
                    parent.setAmount(parentAmount);
                    updateById(parent);
                }
            }
        }
    }

    @Override
    public boolean updateBalanceState(Long rkId, Integer balanceState) {
        CriteriaUpdate cu = new CriteriaUpdate();
        cu.set(true, "balanceState", balanceState);
        cu.eq(true, "rkId", rkId);
        return update(cu);
    }

    public BusSalemanBalance findBySaleManId(Long saleManId, Long companyId) {
        CriteriaQuery cq = new CriteriaQuery(BusSalemanBalance.class);
        cq.eq(true, "saleManId", saleManId);
        cq.eq(true, "companyId", companyId);
        return getOne(cq, false);
    }

    @Override
    public void saveSalManBalance(BusPayment payment) {
        Long saleManId = payment.getSaleManId();
        Long companyId = payment.getCompanyId();
        BusSalemanBalance saleManBalance = findBySaleManId(saleManId, companyId);
        BigDecimal amount = payment.getAmount();
        BigDecimal depositAmount = FlymeUtils.getBigDecimal(payment.getReturnAmount(), "0");
        if (FlymeUtils.isEmpty(saleManBalance)) {
            saleManBalance = new BusSalemanBalance();
            saleManBalance.setRkId(payment.getPaymentId());
            saleManBalance.setCompanyId(payment.getCompanyId());
            saleManBalance.setOrganizationId(payment.getOrganizationId());
            saleManBalance.setAmount(amount.subtract(depositAmount));
            saleManBalance.setDepositAmount(depositAmount);
        } else {
            BigDecimal oldAmount = saleManBalance.getAmount();
            BigDecimal oldDepositAmount = saleManBalance.getAmount();
            //金额累加
            saleManBalance.setAmount(amount.add(oldAmount));
            saleManBalance.setDepositAmount(depositAmount.add(oldDepositAmount));
        }
        saleManBalance.setOptType(CommonConstants.INT_1);
        saleManBalance.setAmountType(CommonConstants.INT_1);
        saleManBalance.setBalanceState(CommonConstants.INT_1);
        saleManBalance.setAmountDate(payment.getAmountDate());
        saleManBalance.setPayBankName(payment.getPayBankName());
        saleManBalance.setPayBankId(payment.getPayBankId());
        saleManBalance.setPayCardNo(payment.getPayBankNo());
        saleManBalance.setVersion(1);
        saleManBalance.setBankId(payment.getBankId());
        saleManBalance.setUserId(payment.getUserId());
        saveOrUpdate(saleManBalance);
    }

    @Override
    public void saveSalManBalance(Long saleManId, BigDecimal amount) {
        BusSaleman saleMan = salemanService.getById(saleManId);
        Long companyId = OpenHelper.getCompanyId();
        BusSalemanBalance saleManBalance = findBySaleManId(saleManId, companyId);
        if (FlymeUtils.isEmpty(saleManBalance) && FlymeUtils.isNotEmpty(saleMan)) {
            saleManBalance = new BusSalemanBalance();
            saleManBalance.setCompanyId(companyId);
            saleManBalance.setOrganizationId(OpenHelper.getOrganizationId());
            saleManBalance.setOptType(CommonConstants.INT_1);
            saleManBalance.setAmountType(CommonConstants.INT_1);
            saleManBalance.setSaleManId(saleManId);
            saleManBalance.setCompanyId(companyId);
            saleManBalance.setDeptId(saleMan.getDeptId());
            saleManBalance.setBalanceState(CommonConstants.INT_1);
            saleManBalance.setVersion(1);
            saleManBalance.setAmountDate(DateUtils.getNowDate());
        }
        saleManBalance.setAmount(amount);
        saleManBalance.setUserId(OpenHelper.getUserId());
        saveOrUpdate(saleManBalance);
    }
}
